package agents;

import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;


@SuppressWarnings("serial")
public class LoserAgent extends Agent {
	
	@SuppressWarnings("unused")
	private AID agentId = null;
	private RegisterAtStrikemaster registerBeh;
	
	// Initialisiert einen Loseragent
	@Override
	protected void setup() {
		System.out.println(getLocalName()+" STARTED");
		
		// Regestrieren des Agenten mit dem DF
		this.agentId = new AID(getLocalName(), AID.ISLOCALNAME);

		ServiceDescription sd = new ServiceDescription();
		DFAgentDescription dfd = new DFAgentDescription();

		sd.setType(ManagementAgent.SERVICEID_LOSER_AGENT);
		sd.setName(getName());

		dfd.setName(getAID());
		dfd.addServices(sd);
		
		try {
			// Register with the Directory Facilitator (DF):
			DFService.register(this, dfd);
			System.out.println(getLocalName()+" registered with DF");
		} catch (FIPAException e) {
			System.err.println(getName() + ": Could not register with DF.");
			doDelete(); // Kill the agent
		}
		
		// Add Behavior das nach einem Strikemaster sucht und sich bei ihm regestriert
		registerBeh = new RegisterAtStrikemaster(this);
		addBehaviour(registerBeh);
		
		// Behaviour zum lesen der erhaltenen Nachrichten
		addBehaviour(new CyclicBehaviour(this) {

			@Override
			public void action() {
				// Auslesen der Nachricht
				MessageTemplate mt = MessageTemplate.MatchPerformative(ACLMessage.INFORM);
				ACLMessage msg = myAgent.receive(mt);
				if (msg != null) {
					// INFORM Message received. Process it
					String msgContent = msg.getContent();
					
					// Nachricht wenn der Agent am Zug ist
					if(msgContent.equals(StrikeAgent.YOUR_TURN)){
						System.out.println(getLocalName()+": it's my turn ");
						ACLMessage registerAtMaster = new ACLMessage(ACLMessage.REQUEST);
						
						registerAtMaster.addReceiver(msg.getSender());

						// Fragt den Sender nach der Anzahl der Streichhoelzer
						registerAtMaster.setContent(StrikeAgent.REQUEST_STRIKES);
						myAgent.send(registerAtMaster);
						
					// Nachricht mit der Anzahl an Streichhoelzern
					} else if (msgContent.contains("STRIKES")) {
						int strikes = Integer.parseInt(msgContent.substring(9));
						// Macht einen Zug
						int move = calculateMove();
						
						System.out.println(getLocalName()+": received current number of strikes: "+strikes);
						System.out.println(getLocalName()+": i take "+move);
						
						ACLMessage informMove = new ACLMessage(ACLMessage.INFORM);
						
						informMove.addReceiver(msg.getSender());

						// Antwortet dem Sender mit der Anzahl der gewaehlten Streichhoelzern
						informMove.setContent(StrikeAgent.REPLY_STRIKES + move);
						myAgent.send(informMove);
					
					// Nachricht wenn der Agent geloescht werden soll
					} else if (msgContent.equals(StrikeAgent.DELETE)) {
						myAgent.doDelete();
					
					// Nachricht wenn der Strikemaster geloescht wurden ist
					// dann wird das Regestrieren Behaviour entfernt und wieder
					// neu hinzugefuegt das sich der Agent beim neuen Strikemaster registriert
					} else if (msgContent.contains(StrikeAgent.RESTART)) {
						myAgent.removeBehaviour(registerBeh);
						registerBeh = new RegisterAtStrikemaster(myAgent);
						myAgent.addBehaviour(registerBeh);
					}
				} else {
					block();
				}
			}
		});
    }
        
	@Override
	protected void takeDown() {
		// Vom DF abmelden
		try {
			DFService.deregister(this);
			System.out.println(getLocalName()+" DEREGISTERED WITH THE DF");
			doDelete();
		} catch (FIPAException e) {
			e.printStackTrace();
		}
	}
	
	// Rechnet Zug aus
	private int calculateMove() {
		// Waehlt eine Zahl zwischen 1 und 3
		return (int) Math.ceil(Math.random()*3);
	}
}